PKG_LICENSE:=GPL-2.0-or-later
-PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/switchdev-poller
endef
define Package/switchdev-poller/description
-This service monitors switchdev ports and brings down CPU ports when
-all related non-CPU vlan ports are also down. Otherwise, it brings
-the port up.
-
+ This service monitors switchdev ports and brings down CPU ports when
+ all related non-CPU vlan ports are also down. Otherwise, it brings
+ the port up.
endef
define Build/Compile
endef
define Package/switchdev-poller/install
- $(CP) ./files/* $(1)
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/switchdev-poller.init $(1)/etc/init.d/switchdev-poller
+ $(INSTALL_DIR) $(1)/usr/lib/switchdev-poller
+ $(INSTALL_BIN) ./files/switchdev-poller $(1)/usr/lib/switchdev-poller/switchdev-poller
endef
$(eval $(call BuildPackage,switchdev-poller))
+++ /dev/null
-#!/bin/sh /etc/rc.common
-
-START=99
-USE_PROCD=1
-
-start_service() {
- procd_open_instance switchdev-poller
- procd_set_param command /usr/lib/switchdev-poller/switchdev-poller
- procd_set_param stdout 1
- procd_set_param stderr 0 # enable for extra debug info
- procd_set_param respawn 3600 5 5
- procd_close_instance
-}
-
-service_triggers() {
- procd_add_reload_trigger network
-}
--- /dev/null
+#!/bin/sh
+# shellcheck disable=SC2039,SC1091
+# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, SC2039: In POSIX sh, string replacement is undefined.
+# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, string indexing is undefined.
+# https://www.shellcheck.net/wiki/SC1091 -- Not following: /lib/functions.sh:...
+#
+# Pools switchdev for port changes
+#
+
+[ -n "$NICED" ] && NICED=1 exec nice -n 19 "$0" "$@"
+
+. /usr/share/libubox/jshn.sh
+. /lib/functions.sh
+
+cpu_ports=""
+
+json_init
+json_load "$(cat /etc/board.json)"
+
+switches=
+json_get_keys switches switch
+json_select switch
+for switch in $switches; do
+ echo Loading $switch >&2
+ json_select "$switch"
+ if json_is_a ports array; then
+ ports=
+ json_get_keys ports ports
+ json_select ports
+
+ for port in $ports; do
+ echo Checking port "$port" in "$switch" >&2
+ json_select "$port"
+ num=
+ json_get_vars num device
+ if [ -n "$device" ]; then
+ echo "Port ${switch}_$num is CPU port as $device" >&2
+ cpu_ports="$cpu_ports ${switch}_$num=$device"
+ fi
+ json_select ..
+ done
+ json_select ..
+ fi
+ json_select ..
+done
+
+each_switch_vlan() {
+ switch=
+ vlan=
+ ports=
+ config_get switch "$1" device
+ config_get vlan "$1" vlan
+ config_get ports "$1" ports
+
+ [ -n "$vlan" ] || { echo "No vlan for '$1'" >&2; return 1; }
+ [ -n "$switch" ] || { echo "No device for '$1'" >&2; return 1; }
+
+ vlan_ifnames=""
+ vlan_non_cpu_ports=""
+ echo Checking vlan "$vlan" in $switch >&2
+ for port in $ports; do
+ case $port in
+ *t) tagged=1; port=${port:0:-1} ;;
+ *) tagged= ;;
+ esac
+ echo "Checking port $port in $switch used by vlan $vlan" >&2
+
+ cpu_port_ifname=""
+ for cpu_port in $cpu_ports; do
+ device=${cpu_port#*=}
+ cpu_switchport=${cpu_port%=*}
+ [ "${cpu_switchport}" = "${switch}_${port}" ] || continue
+ echo "Port $port in $switch used by $vlan is a CPU port at $device" >&2
+
+ for device_tagged in $device_tagged; do
+ [ "${tagged}" = 1 ] && not_tagged=0 || not_tagged=1
+ if [ "$device_tagged" = "$device=${not_tagged}" ]; then
+ echo "Cannot control CPU port ${cpu_switchport} when it is used both as tagged and not tagged"
+ exit 1
+ fi
+ done
+ device_tagged="${device_tagged} ${device}=${tagged:-0}"
+ cpu_port_ifname=${device}${tagged+.$vlan}
+ done
+
+ if [ -n "$cpu_port_ifname" ]; then
+ vlan_ifnames="$vlan_ifnames $cpu_port_ifname"
+ continue
+ fi
+ vlan_non_cpu_ports="$vlan_non_cpu_ports ${port}"
+ done
+ vlan_non_cpu_switch_ports="${vlan_non_cpu_ports// /:${switch}_}"
+ vlan_non_cpu_switch_ports="${vlan_non_cpu_switch_ports:1}"
+ vlan_non_cpu_ports="${vlan_non_cpu_ports:1}"
+ for vlan_ifname in $vlan_ifnames; do
+ devices2ports="$devices2ports $vlan_ifname=${vlan_non_cpu_switch_ports}"
+ echo "Monitoring $switch (ports ${vlan_non_cpu_ports// /,}) for $vlan_ifname"
+ done
+}
+
+device_tagged=""
+devices2ports=""
+config_load network
+config_foreach each_switch_vlan switch_vlan
+
+cleanup() {
+ for device2ports in $devices2ports; do
+ device=${device2ports%=*}
+ ip link show dev ${device}_down >/dev/null 2>&1 && {
+ echo "Bringing up $device on exit..."
+ ip link set dev ${device}_down name ${device}
+ ip link set dev ${device} up >/dev/null 2>&1;
+ }
+ done
+ echo "Stopped poller"
+ exit
+}
+trap cleanup INT TERM
+echo "Starting poller"
+while true; do (
+for device2ports in $devices2ports; do
+ device=${device2ports%=*}
+ switch_ports=${device2ports#*=}
+ switch_ports=${switch_ports//:/ }
+ should_be_up=false
+ for switch_port in $switch_ports; do
+ state=$(eval echo \$${switch_port})
+ if [ -z "${state}" ]; then
+ switch=${switch_port%_*}
+ port=${switch_port#*_}
+ echo "Polling $switch_port..." >&2
+ swconfig dev $switch port $port get link | grep -q 'link:up' &&
+ state=up || state=down
+ eval "$switch_port=$state"
+ echo "State of $switch_port, used by $device, is $state" >&2
+ else
+ echo "State of $switch_port, used by $device, is $state (cached)" >&2
+ fi
+ [ $state = up ] && should_be_up=true
+ done
+
+ if $should_be_up; then
+ ip link show dev ${device}_down >/dev/null 2>&1 && {
+ echo "Bringing up $device..."
+ ip link set dev ${device}_down name ${device}
+ ip link set dev ${device} up >/dev/null 2>&1;
+ }
+ else
+ ip link show dev ${device} >/dev/null 2>&1 && {
+ echo "Bringing down $device..."
+ ip link set dev ${device} down >/dev/null 2>&1;
+ ip link set dev ${device} name ${device}_down
+ }
+
+ fi
+done )
+sleep 3
+done
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+START=99
+USE_PROCD=1
+
+start_service() {
+ procd_open_instance switchdev-poller
+ procd_set_param command /usr/lib/switchdev-poller/switchdev-poller
+ procd_set_param stdout 1
+ procd_set_param stderr 0 # enable for extra debug info
+ procd_set_param respawn 3600 5 5
+ procd_close_instance
+}
+
+service_triggers() {
+ procd_add_reload_trigger network
+}
+++ /dev/null
-#!/bin/sh
-# shellcheck disable=SC2039,SC1091
-# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, SC2039: In POSIX sh, string replacement is undefined.
-# https://www.shellcheck.net/wiki/SC2039 -- In POSIX sh, string indexing is undefined.
-# https://www.shellcheck.net/wiki/SC1091 -- Not following: /lib/functions.sh:...
-#
-# Pools switchdev for port changes
-#
-
-[ -n "$NICED" ] && NICED=1 exec nice -n 19 "$0" "$@"
-
-. /usr/share/libubox/jshn.sh
-. /lib/functions.sh
-
-cpu_ports=""
-
-json_init
-json_load "$(cat /etc/board.json)"
-
-switches=
-json_get_keys switches switch
-json_select switch
-for switch in $switches; do
- echo Loading $switch >&2
- json_select "$switch"
- if json_is_a ports array; then
- ports=
- json_get_keys ports ports
- json_select ports
-
- for port in $ports; do
- echo Checking port "$port" in "$switch" >&2
- json_select "$port"
- num=
- json_get_vars num device
- if [ -n "$device" ]; then
- echo "Port ${switch}_$num is CPU port as $device" >&2
- cpu_ports="$cpu_ports ${switch}_$num=$device"
- fi
- json_select ..
- done
- json_select ..
- fi
- json_select ..
-done
-
-each_switch_vlan() {
- switch=
- vlan=
- ports=
- config_get switch "$1" device
- config_get vlan "$1" vlan
- config_get ports "$1" ports
-
- [ -n "$vlan" ] || { echo "No vlan for '$1'" >&2; return 1; }
- [ -n "$switch" ] || { echo "No device for '$1'" >&2; return 1; }
-
- vlan_ifnames=""
- vlan_non_cpu_ports=""
- echo Checking vlan "$vlan" in $switch >&2
- for port in $ports; do
- case $port in
- *t) tagged=1; port=${port:0:-1} ;;
- *) tagged= ;;
- esac
- echo "Checking port $port in $switch used by vlan $vlan" >&2
-
- cpu_port_ifname=""
- for cpu_port in $cpu_ports; do
- device=${cpu_port#*=}
- cpu_switchport=${cpu_port%=*}
- [ "${cpu_switchport}" = "${switch}_${port}" ] || continue
- echo "Port $port in $switch used by $vlan is a CPU port at $device" >&2
-
- for device_tagged in $device_tagged; do
- [ "${tagged}" = 1 ] && not_tagged=0 || not_tagged=1
- if [ "$device_tagged" = "$device=${not_tagged}" ]; then
- echo "Cannot control CPU port ${cpu_switchport} when it is used both as tagged and not tagged"
- exit 1
- fi
- done
- device_tagged="${device_tagged} ${device}=${tagged:-0}"
- cpu_port_ifname=${device}${tagged+.$vlan}
- done
-
- if [ -n "$cpu_port_ifname" ]; then
- vlan_ifnames="$vlan_ifnames $cpu_port_ifname"
- continue
- fi
- vlan_non_cpu_ports="$vlan_non_cpu_ports ${port}"
- done
- vlan_non_cpu_switch_ports="${vlan_non_cpu_ports// /:${switch}_}"
- vlan_non_cpu_switch_ports="${vlan_non_cpu_switch_ports:1}"
- vlan_non_cpu_ports="${vlan_non_cpu_ports:1}"
- for vlan_ifname in $vlan_ifnames; do
- devices2ports="$devices2ports $vlan_ifname=${vlan_non_cpu_switch_ports}"
- echo "Monitoring $switch (ports ${vlan_non_cpu_ports// /,}) for $vlan_ifname"
- done
-}
-
-device_tagged=""
-devices2ports=""
-config_load network
-config_foreach each_switch_vlan switch_vlan
-
-cleanup() {
- for device2ports in $devices2ports; do
- device=${device2ports%=*}
- ip link show dev ${device}_down >/dev/null 2>&1 && {
- echo "Bringing up $device on exit..."
- ip link set dev ${device}_down name ${device}
- ip link set dev ${device} up >/dev/null 2>&1;
- }
- done
- echo "Stopped poller"
- exit
-}
-trap cleanup INT TERM
-echo "Starting poller"
-while true; do (
-for device2ports in $devices2ports; do
- device=${device2ports%=*}
- switch_ports=${device2ports#*=}
- switch_ports=${switch_ports//:/ }
- should_be_up=false
- for switch_port in $switch_ports; do
- state=$(eval echo \$${switch_port})
- if [ -z "${state}" ]; then
- switch=${switch_port%_*}
- port=${switch_port#*_}
- echo "Polling $switch_port..." >&2
- swconfig dev $switch port $port get link | grep -q 'link:up' &&
- state=up || state=down
- eval "$switch_port=$state"
- echo "State of $switch_port, used by $device, is $state" >&2
- else
- echo "State of $switch_port, used by $device, is $state (cached)" >&2
- fi
- [ $state = up ] && should_be_up=true
- done
-
- if $should_be_up; then
- ip link show dev ${device}_down >/dev/null 2>&1 && {
- echo "Bringing up $device..."
- ip link set dev ${device}_down name ${device}
- ip link set dev ${device} up >/dev/null 2>&1;
- }
- else
- ip link show dev ${device} >/dev/null 2>&1 && {
- echo "Bringing down $device..."
- ip link set dev ${device} down >/dev/null 2>&1;
- ip link set dev ${device} name ${device}_down
- }
-
- fi
-done )
-sleep 3
-done